package com.xxx.control.base.ext

import android.content.res.Resources
import android.view.View
import com.xxx.control.net.NetWorkException
import com.xxx.control.R
import com.xxx.control.constant.Constant
import com.xxx.control.net.ApiService
import com.xxx.control.net.BaseResponse
import com.xxx.control.net.RetrofitManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

/**
 * date: 2020/09/07
 * desc: 拓展函数
 */
/**
 * 接口数据装换
 * @receiver BaseResponse<T>
 * @return T
 */
fun <T> BaseResponse<T>.dataConvert(

): T {
    when (code) {
        Constant.Code.OK -> {
            return data
        }
        Constant.Code.UnAuthorized -> {
//            SpUtil.save("access_token", "")
            throw NetWorkException(msg, code)
        }
        else -> {
            throw NetWorkException(msg, code)
        }
    }
}

/**
 * 接口数据无data 转换
 * @receiver BaseResponse<T>
 * @param loadState MutableLiveData<BaseActionEvent>?
 * @return Boolean
 */
fun <T> BaseResponse<T>.noDataConvert(): Boolean {
    when (code) {
        Constant.Code.OK -> {
            return true
        }
        Constant.Code.UnAuthorized -> {
//            SpUtil.save("access_token", "")
            throw NetWorkException(msg, code)
        }
        else -> {
            throw NetWorkException(msg, code)
        }

    }
}


fun <T> Flow<BaseResponse<T>>.subscribe(
    scope: CoroutineScope, success: (T) -> Unit,
    onServerError: (NetWorkException) -> Unit = {}
) {
    this.onEach {

        when (it.code) {
            Constant.Code.OK -> {
                success(it.data)
            }
            Constant.Code.UnAuthorized -> {
                throw NetWorkException(it.msg, it.code)
            }
            else -> {
                throw NetWorkException(it.msg, it.code)
            }
        }
    }.catch {
        val exception = NetWorkException(it)
        onServerError(exception)

    }.launchIn(scope)
}


/**
 * 单位转换
 * 正常编码中一般只会用到 [dp]/[sp] ;
 * 其中[dp]/[sp] 会根据系统分辨率将输入的dp/sp值转换为对应的px
 */
val Float.dp: Float
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_DIP,
        this,
        Resources.getSystem().displayMetrics
    )

val Int.dp: Int
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_DIP,
        this.toFloat(),
        Resources.getSystem().displayMetrics
    ).toInt()

val Float.sp: Float                 // [xxhdpi](360 -> 1080)
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_SP, this, Resources.getSystem().displayMetrics
    )

val Int.sp: Int
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_SP,
        this.toFloat(),
        Resources.getSystem().displayMetrics
    ).toInt()


/**
 * get set
 * 给view添加一个上次触发时间的属性（用来屏蔽连击操作）
 */
private var <T : View>T.triggerLastTime: Long
    get() = if (getTag(R.id.triggerLastTimeKey) != null) getTag(R.id.triggerLastTimeKey) as Long else 0
    set(value) {
        setTag(R.id.triggerLastTimeKey, value)
    }

/**
 * get set
 * 给view添加一个延迟的属性（用来屏蔽连击操作）
 */
private var <T : View>T.triggerDelay: Long
    get() = if (getTag(R.id.triggerDelayKey) != null) getTag(R.id.triggerDelayKey) as Long else -1
    set(value) {
        setTag(R.id.triggerDelayKey, value)
    }

/**
 * 判断时间是否满足再次点击的要求（控制点击）
 * @receiver T
 * @return Boolean
 */
private fun <T : View> T.clickEnable(): Boolean {
    var clickable = false
    val currentClickTiem = System.currentTimeMillis()
    if (currentClickTiem - triggerLastTime >= triggerDelay) {
        clickable = true
    }
    triggerLastTime = currentClickTiem
    return clickable
}

/***
 * 带延迟过滤点击事件的 View 扩展 防止快速点击
 * @param delay Long 延迟时间，默认500毫秒
 * @param block: (T) -> Unit 函数
 * @return Unit
 */

fun <T : View> T.clickWithTrigger(delay: Long = 500, block: (T) -> Unit) {
    triggerDelay = delay
    setOnClickListener {
        if (clickEnable()) {
            block(this)
        }
    }
}

/**
 * 日志打印拓展
 * @receiver Any
 * @param tag String
 */
fun Any.logd(tag: String = "logd----->") {
//    Timber.tag(tag).d(this.toString())
}

/**
 * 日志打印拓展
 * @receiver Any
 * @param tag String
 */
fun Any.loge(tag: String = "loge----->") {
//    Timber.tag(tag).e(this.toString())
}

/**
 * @desc 多个view执行同样的方法
 *  eg:  多个view点击时 跳转同一个页面
 */
fun clickWithMultiView(vararg v: View, block: () -> Unit) {
    v.forEach {
        it.clickWithTrigger {
            block.invoke()
        }
    }
}

fun getApiService(): ApiService {
    return RetrofitManager.build().create(ApiService::class.java)
}

fun getApiServiceTest(): ApiService {
    return RetrofitManager.build().createTest(ApiService::class.java)
}